package com.tongcao.cn.netty.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;

/**
 * @author:tongcao
 * @since:2019/7/8 17:26
 * Description:
 */
public class NioServer implements Runnable {


    private final int BUFFER_SIZE = 1024; // 缓冲区大小
    private final int PORT = 8888;        // 监听的端口

    private Selector selector;// 多路复用器，NIO编程的基础，负责管理通道Channel

    // 缓冲区Buffer，和BIO的一个重要区别（NIO读写数据是在缓冲区中进行，而BIO是通过流的形式）
    private ByteBuffer readBuffer = ByteBuffer.allocate(BUFFER_SIZE);

    public NioServer() {
        start();
    }


    private void start() {
        try {
            // 1.开启多路复用器
            selector = Selector.open();
            // 2.打开服务器通道(网络读写通道)
            final ServerSocketChannel channel = ServerSocketChannel.open();
            // 3.设置服务器通道为非阻塞模式，true为阻塞，false为非阻塞
            channel.configureBlocking(false);
            // 4.绑定端口
            channel.socket().bind(new InetSocketAddress(PORT));
            // 5.把通道注册到多路复用器上，并监听阻塞事件
            /**
             * SelectionKey.OP_READ 	: 表示关注读数据就绪事件
             * SelectionKey.OP_WRITE 	: 表示关注写数据就绪事件
             * SelectionKey.OP_CONNECT: 表示关注socket channel的连接完成事件
             * SelectionKey.OP_ACCEPT : 表示关注server-socket channel的accept事件
             */
            channel.register(selector, SelectionKey.OP_ACCEPT);
            System.out.println("Server start >>>>>>>>> port :" + PORT);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 需要一个线程负责Selector的轮询
    @Override
    public void run() {

    }

    private void accept(SelectionKey selectionKey) {
        try {
            // 1.获取通道服务
            final ServerSocketChannel channel = (ServerSocketChannel) selectionKey.channel();
            // 2.执行阻塞方法
            final SocketChannel socketChannel = channel.accept();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        new Thread(new NioServer()).start();
    }
}